package com.example.security1.web.user.controller;

import com.alibaba.fastjson.JSON;
import com.example.security1.config.jwt.JwtUtils;
import com.example.security1.config.redis.RedisService;
import com.example.security1.util.MakeMenuTree;
import com.example.security1.util.vo.Resp;
import com.example.security1.util.vo.ResultVO;
import com.example.security1.util.vo.RouterVO;
import com.example.security1.util.vo.TokenVO;
import com.example.security1.web.menu.entity.Menu;
import com.example.security1.web.menu.service.MenuService;
import com.example.security1.web.user.entity.User;
import com.example.security1.web.user.entity.UserInfo;
import com.example.security1.web.user.service.UserService;
import io.jsonwebtoken.Jwts;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import lombok.RequiredArgsConstructor;
import org.apache.commons.lang3.StringUtils;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.web.authentication.logout.SecurityContextLogoutHandler;
import org.springframework.web.bind.annotation.*;

import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.Optional;

@RestController
@RequestMapping("/api/user")
@RequiredArgsConstructor
public class UserController {

    private final UserService userService;
    private final MenuService menuService;
    private final RedisService redisService;
    private final JwtUtils jwtUtils;

    /**
     * 获取用户列表
     * @return 用户列表
     */
    @GetMapping("/getList")
    public String getAllUser() {
        return JSON.toJSONString(userService.list());
    }

    /**
     * 获取登录用户的信息
     * @return 用户信息
     */
    @GetMapping("/userInfo")
    public String getUserInfo() {
        // 从 SpringSecurity 上下文中获取用户信息
        Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
        User user = (User)authentication.getPrincipal();
        UserInfo userInfo = new UserInfo();
        userInfo.setId(user.getUId());
        userInfo.setUsername(user.getUsername());
        userInfo.setAvatar(user.getAvatar());
        List<Menu> permissionList = user.getPermissionList();
        Object[] array = permissionList.stream()
                .filter(Objects::nonNull)
                .map(Menu::getCode)
                .toArray();
        userInfo.setPermissionList(array);
        return JSON.toJSONString(userInfo);
    }

    /**
     * 获取菜单列表
     * @return 菜单列表
     */
//    @PreAuthorize("hasAuthority('sys:user')")
    @GetMapping("/getMenuList/{uId}")
    public ResultVO<Object> getMenuList(@PathVariable("uId") Integer uId) {
        System.out.println("获取菜单信息的用户: " + uId);
        User user = userService.getById(uId);
        List<Menu> menuList;
        if (user.getIsAdmin().equals(1)) {
            menuList  = menuService.list();
        } else {
            menuList = menuService.getMenuListByUserId(user.getUId());
        }
        // 获取菜单和目录
        List<Menu> collect = Optional.ofNullable(menuList).orElse(new ArrayList<>())
                .stream()
                .filter(item -> item != null && !item.getType().equals("2"))
                .toList();
        List<RouterVO> router = MakeMenuTree.makeRouter(collect, 0L);
        return Resp.success("查询成功", router);
    }

    /**
     * 刷新token
     * @return 新的token
     */
    @PostMapping("/refreshToken")
    public ResultVO<Object> refresh(HttpServletRequest request) {
        // 获取token
        String token = request.getHeader("token");
        if (StringUtils.isEmpty(token)) {
            token = request.getParameter("token");
        }
        // 获取用户信息
        Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
        UserDetails userDetails = (UserDetails)authentication.getPrincipal();
        // 验证token
        Boolean tokenBoolean = jwtUtils.validateToken(token, userDetails);
        // 验证失败返回
        if (!tokenBoolean)
            return Resp.error("token验证失败");
        // 验证成功，获取新的token
        String refreshToken = jwtUtils.refreshToken(token);
        // 获取新的token的过期时间
        Long expireTime = Jwts.parser()
                .setSigningKey(jwtUtils.getSecret())
                .parseClaimsJws(refreshToken)
                .getBody()
                .getExpiration().getTime();
        TokenVO tokenVO = new TokenVO();
        tokenVO.setToken(refreshToken);
        tokenVO.setExpireTime(expireTime);
        // 将之前redis中的token删除
        String delOldTokenKey = "token_" + token;
        redisService.delete(delOldTokenKey);
        // 将新的token存到redis
        String newTokenKey = "token_" + refreshToken;
        redisService.set(newTokenKey, refreshToken, expireTime);
        return Resp.success("token刷新成功", tokenVO);
    }

    /**
     * 退出登录
     * @return 退出登录信息
     */
    @PostMapping("/loginOut")
    public ResultVO<Object> loginOut(HttpServletRequest request, HttpServletResponse response) {
        // 获取token
        String token = request.getHeader("token");
        if (StringUtils.isEmpty(token)) {
            token = request.getParameter("token");
        }
        // 在 Security 上下文中获取用户认证信息
        Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
        if (authentication != null) {
            // 清空用户信息
            new SecurityContextLogoutHandler().logout(request, response, authentication);
            // 删除redis中的token
            String delTokenKey = "token_" + token;
            redisService.delete(delTokenKey);
        }
        Authentication newAuthentication = SecurityContextHolder.getContext().getAuthentication();
        System.out.println(newAuthentication);
        return Resp.success("退出登录成功");
    }

}
